import { Module } from 'vuex'
import { MESSAGE_TYPE, MESSAGE_STATUS } from '../common/enums'
import userStore, { IUserState } from './userStore'

interface IDateMessage {
  sendTime: number
  type: MESSAGE_TYPE
}

export interface IMessage extends IDateMessage {
  content: string
  id: number
  recvId: number
  selfSend: boolean
  sendId: number
  status: number
  loadStatus?: string
}

interface IChat {
  atAll: boolean
  atMe: boolean
  headImage: string
  lastContent: string
  lastSendTime: number // Date
  lastTimeTip?: number
  messages: (IMessage | IDateMessage)[]
  showName: string
  targetId: number
  type: string
  unreadCount: number
  sendNickName?: string
}

export interface IChatState {
  activeIndex: number
  chats: IChat[]
  privateMsgMaxId: number
  groupMsgMaxId: number
  loadingPrivateMsg: boolean
  loadingGroupMsg: boolean
}

const chatStore: Module<IChatState, any> = {
  state: {
    activeIndex: -1,
    chats: [],
    privateMsgMaxId: 0,
    groupMsgMaxId: 0,
    loadingPrivateMsg: false,
    loadingGroupMsg: false
  },

  mutations: {
    initChats(state, chatsData: { chats: IChat[]; groupMsgMaxId: number; privateMsgMaxId: number }) {
      state.chats = chatsData.chats || []
      state.privateMsgMaxId = chatsData.privateMsgMaxId || 0
      state.groupMsgMaxId = chatsData.groupMsgMaxId || 0
      // 防止图片一直处在加载中状态
      state.chats.forEach((chat) => {
        const messages = chat.messages as IMessage[]
        messages.forEach((msg) => {
          if (msg.loadStatus == 'loading') {
            msg.loadStatus = 'fail'
          }
        })
      })
    },
    openChat(state, chatInfo) {
      let chat: IChat | null = null
      for (let index in state.chats) {
        if (state.chats[index].type == chatInfo.type && state.chats[index].targetId === chatInfo.targetId) {
          chat = state.chats[index]
          // 放置头部
          this.commit('moveTop', index)
          break
        }
      }
      // 创建会话
      if (chat == null) {
        chat = {
          targetId: chatInfo.targetId,
          type: chatInfo.type,
          showName: chatInfo.showName,
          headImage: chatInfo.headImage,
          lastContent: '',
          lastSendTime: new Date().getTime(),
          unreadCount: 0,
          messages: [],
          atMe: false,
          atAll: false
        }
        state.chats.unshift(chat)
      }
      this.commit('saveToStorage')
    },
    activeChat(state, index) {
      state.activeIndex = index
      if (index >= 0) {
        state.chats[index].unreadCount = 0
      }
    },
    resetUnreadCount(state, chatInfo) {
      for (let index in state.chats) {
        if (state.chats[index].type == chatInfo.type && state.chats[index].targetId == chatInfo.targetId) {
          state.chats[index].unreadCount = 0
          state.chats[index].atMe = false
          state.chats[index].atAll = false
        }
      }
      this.commit('saveToStorage')
    },
    readedMessage(state, pos) {
      for (let index = 0; index < state.chats.length; index++) {
        if (state.chats[index].type == 'PRIVATE' && state.chats[index].targetId == pos.friendId) {
          const messages = state.chats[index].messages as IMessage[]
          messages.forEach((m) => {
            if (m.selfSend && m.status != MESSAGE_STATUS.RECALL) {
              // pos.maxId为空表示整个会话已读
              if (!pos.maxId || m.id <= pos.maxId) {
                m.status = MESSAGE_STATUS.READED
              }
            }
          })
        }
      }
      this.commit('saveToStorage')
    },
    removeChat(state, index) {
      state.chats.splice(index, 1)
      this.commit('saveToStorage')
    },
    removeGroupChat(state, groupId) {
      for (let index in state.chats) {
        if (state.chats[index].type == 'GROUP' && state.chats[index].targetId == groupId) {
          this.commit('removeChat', index)
        }
      }
    },
    removePrivateChat(state, userId) {
      for (let index in state.chats) {
        if (state.chats[index].type == 'PRIVATE' && state.chats[index].targetId == userId) {
          this.commit('removeChat', index)
        }
      }
    },
    moveTop(state, index) {
      // 加载中不移动，很耗性能
      if (state.loadingPrivateMsg || state.loadingGroupMsg) {
        return
      }
      if (index > 0) {
        let chat = state.chats[index]
        state.chats.splice(index, 1)
        state.chats.unshift(chat)
        this.commit('saveToStorage')
      }
    },
    insertMessage(state, msgInfo) {
      // 获取对方id或群id
      let type = msgInfo.groupId ? 'GROUP' : 'PRIVATE'
      let targetId = msgInfo.groupId ? msgInfo.groupId : msgInfo.selfSend ? msgInfo.recvId : msgInfo.sendId
      let chat: IChat | null = null
      for (let index in state.chats) {
        if (state.chats[index].type == type && state.chats[index].targetId === targetId) {
          chat = state.chats[index]
          this.commit('moveTop', index)
          break
        }
      }
      if (!chat) return
      // 会话列表内容
      if (!state.loadingPrivateMsg && !state.loadingPrivateMsg) {
        if (msgInfo.type == MESSAGE_TYPE.IMAGE) {
          chat.lastContent = '[图片]'
        } else if (msgInfo.type == MESSAGE_TYPE.FILE) {
          chat.lastContent = '[文件]'
        } else if (msgInfo.type == MESSAGE_TYPE.AUDIO) {
          chat.lastContent = '[语音]'
        } else {
          chat.lastContent = msgInfo.content
        }
        chat.lastSendTime = msgInfo.sendTime
        chat.sendNickName = msgInfo.sendNickName
      }
      // 未读加1
      if (!msgInfo.selfSend && msgInfo.status != MESSAGE_STATUS.READED) {
        chat.unreadCount++
      }
      // 是否有人@我
      if (!msgInfo.selfSend && chat.type == 'GROUP' && msgInfo.atUserIds && msgInfo.status != MESSAGE_STATUS.READED) {
        let userId = (userStore.state as IUserState).userInfo.id
        if (msgInfo.atUserIds.indexOf(userId) >= 0) {
          chat.atMe = true
        }
        if (msgInfo.atUserIds.indexOf(-1) >= 0) {
          chat.atAll = true
        }
      }
      // 记录消息的最大id
      if (msgInfo.id && type == 'PRIVATE' && msgInfo.id > state.privateMsgMaxId) {
        state.privateMsgMaxId = msgInfo.id
      }
      if (msgInfo.id && type == 'GROUP' && msgInfo.id > state.groupMsgMaxId) {
        state.groupMsgMaxId = msgInfo.id
      }
      // 如果是已存在消息，则覆盖旧的消息数据
      for (let index = 0; index < chat.messages.length; index++) {
        const message = chat.messages[index] as IMessage
        if (msgInfo.id && message.id == msgInfo.id) {
          Object.assign(message, msgInfo)
          this.commit('saveToStorage')
          return
        }
        // 正在发送中的消息可能没有id,通过发送时间判断
        if (msgInfo.selfSend && message.selfSend && message.sendTime == msgInfo.sendTime) {
          Object.assign(message, msgInfo)
          this.commit('saveToStorage')
          return
        }
      }
      // 间隔大于10分钟插入时间显示
      if (!chat.lastTimeTip || chat.lastTimeTip < msgInfo.sendTime - 600 * 1000) {
        chat.messages.push({
          sendTime: msgInfo.sendTime,
          type: MESSAGE_TYPE.TIP_TIME
        })
        chat.lastTimeTip = msgInfo.sendTime
      }
      // 新的消息
      chat.messages.push(msgInfo)
      this.commit('saveToStorage')
    },
    deleteMessage(state, msgInfo) {
      // 获取对方id或群id
      let type = msgInfo.groupId ? 'GROUP' : 'PRIVATE'
      let targetId = msgInfo.groupId ? msgInfo.groupId : msgInfo.selfSend ? msgInfo.recvId : msgInfo.sendId
      let chat: IChat | null = null
      for (let index in state.chats) {
        if (state.chats[index].type == type && state.chats[index].targetId === targetId) {
          chat = state.chats[index]
          break
        }
      }
      if (!chat) return
      for (let index = 0; index < chat.messages.length; index++) {
        const message = chat.messages[index] as IMessage
        // 已经发送成功的，根据id删除
        if (message.id && message.id == msgInfo.id) {
          chat.messages.splice(index, 1)
          break
        }
        // 正在发送中的消息可能没有id，根据发送时间删除
        if (msgInfo.selfSend && message.selfSend && message.sendTime == msgInfo.sendTime) {
          chat.messages.splice(index, 1)
          break
        }
      }
      this.commit('saveToStorage')
    },
    updateChatFromFriend(state, friend) {
      for (let i in state.chats) {
        let chat = state.chats[i]
        if (chat.type == 'PRIVATE' && chat.targetId == friend.id) {
          chat.headImage = friend.headImageThumb
          chat.showName = friend.nickName
          break
        }
      }
      this.commit('saveToStorage')
    },
    updateChatFromGroup(state, group) {
      for (let i in state.chats) {
        let chat = state.chats[i]
        if (chat.type == 'GROUP' && chat.targetId == group.id) {
          chat.headImage = group.headImageThumb
          chat.showName = group.remark
          break
        }
      }
      this.commit('saveToStorage')
    },
    loadingPrivateMsg(state, loadding) {
      state.loadingPrivateMsg = loadding
      if (!state.loadingPrivateMsg && !state.loadingGroupMsg) {
        this.commit('refreshChats')
      }
    },
    loadingGroupMsg(state, loadding) {
      state.loadingGroupMsg = loadding
      if (!state.loadingPrivateMsg && !state.loadingGroupMsg) {
        this.commit('refreshChats')
      }
    },
    refreshChats(state) {
      state.chats.forEach((chat) => {
        if (chat.messages.length > 0) {
          let msgInfo = chat.messages[chat.messages.length - 1] as IMessage
          if (msgInfo.type == MESSAGE_TYPE.IMAGE) {
            chat.lastContent = '[图片]'
          } else if (msgInfo.type == MESSAGE_TYPE.FILE) {
            chat.lastContent = '[文件]'
          } else if (msgInfo.type == MESSAGE_TYPE.AUDIO) {
            chat.lastContent = '[语音]'
          } else {
            chat.lastContent = msgInfo.content
          }
          chat.lastSendTime = msgInfo.sendTime
        } else {
          chat.lastContent = ''
          chat.lastSendTime = new Date().getTime()
        }
      })
      state.chats.sort((chat1, chat2) => {
        return chat2.lastSendTime - chat1.lastSendTime
      })
    },
    saveToStorage(state) {
      let userId = (userStore.state as IUserState).userInfo.id
      let key = 'chats-' + userId
      let chatsData = {
        privateMsgMaxId: state.privateMsgMaxId,
        groupMsgMaxId: state.groupMsgMaxId,
        chats: state.chats
      }
      uni.setStorage({
        key: key,
        data: chatsData
      })
    },
    clear(state) {
      state.chats = []
      state.activeIndex = -1
      state.privateMsgMaxId = 0
      state.groupMsgMaxId = 0
      state.loadingPrivateMsg = false
      state.loadingGroupMsg = false
    }
  },
  actions: {
    loadChat(context): Promise<any> {
      return new Promise((resolve, reject) => {
        let userId = (userStore.state as IUserState).userInfo.id
        uni.getStorage({
          key: 'chats-' + userId,
          success(res) {
            context.commit('initChats', res.data)
            resolve(res)
          },
          fail(e) {
            resolve(e)
          }
        })
      })
    }
  }
}

export default chatStore
